-module(homework_router).
-export([start/0,
	 user_registry/1,
	 send/2,
	 get_all/0,
	 push_data_handler/2,
	 start_push_data_handler/2]).
-include("records.hrl").

% Start all processes used by this module.
start() ->
	register(user_registry, spawn(homework_router, user_registry, [[]])).
	

% This function is called from the out(A) of the homework_router.yaws file
% It will store the name and the cookie of the user on the name registry and then execute the push_data_handler
start_push_data_handler(Name, Cookie) ->
	HandlerPid = self(),
	spawn(fun() -> 
		user_registry ! {add, Name, Cookie, self()}, 
		push_data_handler(HandlerPid, Cookie) 
	end),
	[{header, {cache_control, "no-cache"}},
	{streamcontent, "text/plain", " "}].
     

% This function is on charge of receiving the homework actions sent by a user and send it to the correct user
% through the stream_chunk_deliver function
% When it has received the message, it removes the pages from the registry.
push_data_handler(HandlerPid, Cookie) ->
	receive
		stop -> 
			yaws_api:stream_chunk_deliver(HandlerPid, ""),
			yaws_api:stream_chunk_end(HandlerPid),
			user_registry ! {remove, {pid, self()}};
		homework_to_do ->
			% Update the session
			{ok, Session} = yaws_api:cookieval_to_opaque(Cookie),
			{atomic, ToDo} = db_homework_to_do:get(Session#session.user),
			NewSession = Session#session{homework_to_do = length(ToDo)},
			yaws_api:replace_cookie_session(Cookie, NewSession),
			
			% Send the message 
			yaws_api:stream_chunk_deliver(HandlerPid, "homework_to_do"),
			yaws_api:stream_chunk_end(HandlerPid),
			user_registry ! {remove, {pid, self()}};
		homework_to_correct ->
			% Update the session
			{ok, Session} = yaws_api:cookieval_to_opaque(Cookie),
			{atomic, ToCorrect} = db_homework_to_correct:get(Session#session.user),
			NewSession = Session#session{homework_to_correct = length(ToCorrect)},
			yaws_api:replace_cookie_session(Cookie, NewSession),
			
			% Send the message 
			yaws_api:stream_chunk_deliver(HandlerPid, "homework_to_correct"),
			yaws_api:stream_chunk_end(HandlerPid),
			user_registry ! {remove, {pid, self()}};
		homework_to_rate ->
			% Update the session
			{ok, Session} = yaws_api:cookieval_to_opaque(Cookie),
			{atomic, ToRate} = db_homework_to_rate:get(Session#session.user),
			NewSession = Session#session{homework_to_rate = length(ToRate)},
			yaws_api:replace_cookie_session(Cookie, NewSession),
			
			% Send the message 
			yaws_api:stream_chunk_deliver(HandlerPid, "homework_to_rate"),
			yaws_api:stream_chunk_end(HandlerPid),
			user_registry ! {remove, {pid, self()}};
		{homework_finished, Rating} ->
			io:format("heigato~n~n",[]),
			% Update the session
			{ok, Session} = yaws_api:cookieval_to_opaque(Cookie),
			{atomic, [{user, _, Name, _, _, _, _, _, _, HGiven, _, RatingH, _, _, _, _}]} = db_user:get_user(Session#session.user),
			NewRating = (HGiven / (HGiven + 1)) * RatingH + (1 / (HGiven + 1)) * Rating,
			db_user:add_homework_given(Name, NewRating),
			NewSession = Session#session{homework_given = HGiven + 1, rating_homework = NewRating},
			yaws_api:replace_cookie_session(Cookie, NewSession),
			
			user_registry ! {remove, {pid, self()}}
	after 30000 ->
		yaws_api:stream_chunk_deliver(HandlerPid, "timeout"),
		yaws_api:stream_chunk_end(HandlerPid),
		user_registry ! {remove, {pid, self()}}
	end.
    

% Each user is mapped with his username, cookie and the PID of his handler.
% This function keeps track of all this information. 
user_registry(UserList) ->    
	receive
		{add, Name, Cookie, Pid} ->
			NewList = user_registry_add(Name, Cookie, Pid, UserList),
			user_registry(NewList);
		{remove, {name, Name}} ->
			NewList = user_registry_remove_by_name(Name, UserList),
			user_registry(NewList);
		{remove, {pid, Pid}} ->
			NewList = user_registry_remove_by_pid(Pid, UserList),
			user_registry(NewList);
		{From, get, Name} ->
			user_registry_get(From, Name, UserList),
			user_registry(UserList);
		{From, get_all} ->
			user_registry_get_all(From, UserList),
			user_registry(UserList)
	end.


user_registry_add(Name, Cookie, Pid, UserList) ->
	lists:keydelete(Name, 1, UserList),
	[{Name, Cookie, Pid} | UserList].

user_registry_remove_by_name(Name, UserList) ->
	lists:keydelete(Name, 1, UserList).

user_registry_remove_by_pid(Pid, UserList) ->
	lists:keydelete(Pid, 3, UserList).

user_registry_get(From, Name, UserList) ->
	case lists:keysearch(Name, 1, UserList) of
		{value, {_, _, Pid}} -> 
			From ! {result, {Name, Pid}};
		false ->
			From ! {result, false}
	end.

user_registry_get_all(From, UserList) ->
    From ! {result, UserList}.



% This function sends a message to the user Name.
% This message will be treated in the push_data_handler function
send(Name, Message) ->
	user_registry ! {self(), get, Name},
	receive
		{result, {_, Pid}} ->
			Pid ! Message
	after 3000 ->
			user_registry ! {self(), get, Name},
			receive
				{result, {_, Pid}} ->
					Pid ! Message;
				{result, false} ->
					true
			end
	end.


	    
% Returns a list of {Name,Pid} for all active pages.
get_all() ->
	user_registry ! {self(), get_all},
	receive 
		{result, X} -> X
	end.

